package se.liu.oschi129.game.objects.enemies;

import java.awt.Shape;
import java.awt.geom.Rectangle2D;

import se.liu.oschi129.game.objects.ObjectPlayer;
import se.liu.oschi129.game.setspace.AnimatedSetToad;
import se.liu.oschi129.shapefactory.ShapeFactory;
import se.liu.oschi129.timer.Timer;
import se.liu.oschi129.world.model.World;
import se.liu.oschi129.world.objects.WorldMovableCharacterObject;
import se.liu.oschi129.world.objects.WorldObject;

/**
 * This is an enemy toad. It will run after the player in order to hit him.
 * 
 * @author oschi129
 */
public class ObjectEnemyToadRunning extends WorldMovableCharacterObject implements EnemyObject, DefeatableEnemyObject {
	
	// The target of the enemy
	private WorldObject target;
	
	// A motion timer
	private final Timer cooldown;
	
	/**
	 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	 * - - - - - - - - - - - - Constructors - - - - - - - - - - - 
	 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	 */
	
	public ObjectEnemyToadRunning(double x, double y) {
		super(Type.SOFT, new AnimatedSetToad(), true, x, y, 24, 32);
		cooldown = new Timer();
		setAnimation(getAnimationSet().getMoveRightAnimation());
		setImageSpeed(0.5);
		setTarget(null);
		setMaskFactory(new DefaultMask());
	}
	
	/**
	 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	 * - - - - - - - - - - - Public methods - - - - - - - - - - 
	 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	 */
	
	@Override public void performDestructionAction(World world) {
		world.addObjectSynchronized(new ObjectEnemyDead(getAnimationSet().getDeathAnimation(), getX(), getY(), getWidth(), getHeight()));
	}
	
	@Override public void performStepAction(World world) {
		super.performStepAction(world);
		// Addapt to the world physical rules if they are not set
		if (getPhysicalRules() == null)
			setPhysicalRules(world.getPhysicalRules());
		realizeGravity(world);
		// Check if the enemy is in the air
		boolean inAir = world.placeFree(this, getX(), getY() + 2);
		// Focus on a target if the target is not set
		if (getTarget() == null)
			setTarget(world.objectExists(ObjectPlayer.class));
		else
			moveCharacter(world,inAir);
		// Select animation for the enemy
		animateCharacter(inAir);
	}
	
	/**
	 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	 * - - - - - - - - - - Private methods - - - - - - - - - - 
	 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	 */
	
	/** Sets the target of the enemy */
	private void setTarget(WorldObject target) {
		this.target = target;
	}
	
	/** Returns the target of the enemy */
	private WorldObject getTarget() {
		return target;
	}
	
	/** Move the enemy and make the */
	private void moveCharacter(World world, boolean inAir) {
		if (cooldown.cool()) {
			cooldown.set(30);
			if (getTarget().getX() > getX())
				setHorizontalSpeed(3);
			else
				setHorizontalSpeed(-3);
			if (Math.abs(getTarget().getX() - getX()) <= 64) {
				if (!inAir)
					setVerticalSpeed(-8);
			}
		}
		cooldown.tick();
		if (!world.placeFree(this, getX() + getHorizontalSpeed(), getY())) 
			setHorizontalSpeed(-getHorizontalSpeed());
		for (WorldObject obj : world.getObjects()) {
			if (obj instanceof ObjectEnemyToadCollider && collision(obj)) {
				 // Move to the previous position
				setX(getX() - getHorizontalSpeed());
				setHorizontalSpeed(-getHorizontalSpeed());
			}
		}
	}
	
	/** Select the animation for the enemy */
	private void animateCharacter(boolean  inAir) {
		if (getHorizontalSpeed() > 0) {
			if (inAir)
				setAnimation(getAnimationSet().getJumpRightAnimation());
			else
				setAnimation(getAnimationSet().getMoveRightAnimation());
		} else {
			if (inAir)
				setAnimation(getAnimationSet().getJumpLeftAnimation());
			else
				setAnimation(getAnimationSet().getMoveLeftAnimation());
		}
	}
	
	/**
	 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	 * - - - - - - - - - - Private classes - - - - - - - - - - -
	 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	 */
	
	/** Defines the default mask for the enemy*/
	private class DefaultMask implements ShapeFactory {
		
		public Shape makeShape(double x, double y, double width, double height) {
			return new Rectangle2D.Double(x+8,y+8,width-16,height-8);
		}
		
	}
	
}
